package com.lzp.controller.intercepter;

import com.lzp.utils.JsonUtils;
import com.lzp.utils.RedisOperator;
import com.lzp.utils.ServerResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;

/**
 * @author lzp
 * @Description: 定义Token会话拦截器
 * @date 2021/4/24
 */
public class UserTokenInterceptor implements HandlerInterceptor {

    public static final String REDIS_USER_TOKEN = "redis_user_token";

    @Autowired
    private RedisOperator redis;

    /**
     * 拦截请求，在访问controller调用之前
     */
    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) throws Exception {
        String userId = request.getHeader("headerUserId");
        String userToken = request.getHeader("headerUserToken");
        // 1 校验前端userId和token
        if (StringUtils.isNotBlank(userId) && StringUtils.isNotBlank(userToken)) {
            // 2 校验Redis中token
            String redisUserToken = redis.get(REDIS_USER_TOKEN + ":" + userId);
            if (StringUtils.isBlank(redisUserToken)) {
                throwErrorHint(response, ServerResponse.createByErrorMsg("请登录..."));
                return false;
            } else {
                // 3 匹配token
                if (!redisUserToken.equals(userToken)) {
                    throwErrorHint(response, ServerResponse.createByErrorMsg(
                            "账号在异地登录，请重新登录"));
                    return false;
                }
            }
        } else {
            throwErrorHint(response, ServerResponse.createByErrorMsg("请登录..."));
            return false;
        }

        return true;
    }

    /**
     * 通过HttpServletResponse抛出错误提示
     *
     * @param response
     * @param result
     */
    private void throwErrorHint(HttpServletResponse response,
                                ServerResponse result) {
        OutputStream output = null;
        try {
            response.setCharacterEncoding("utf-8");
            response.setContentType("text/json");
            output = response.getOutputStream();
            output.write(JsonUtils.objectToJson(result).getBytes("utf-8"));
            output.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (output != null) {
                    output.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

    /**
     * 请求访问controller之后，渲染视图之前
     */
    @Override
    public void postHandle(HttpServletRequest request,
                           HttpServletResponse response,
                           Object handler,
                           ModelAndView modelAndView) throws Exception {
    }

    /**
     * 请求访问controller之后，渲染视图之后
     */
    @Override
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response,
                                Object handler,
                                Exception ex) throws Exception {
    }
}
